package com.example.aicooking.service.imp;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.example.aicooking.entity.ChatResponse;
import com.example.aicooking.entity.DifyMessageRequest;
import com.example.aicooking.entity.DifyProperties;
import com.example.aicooking.entity.ImageRecord;
import com.example.aicooking.entity.dto.FoodRecognitionDTO;
import com.example.aicooking.mapper.ImageRecordMapper;
import com.example.aicooking.service.ImageService;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import jakarta.annotation.PostConstruct;
import lombok.extern.slf4j.Slf4j;

import okhttp3.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;
import org.springframework.web.multipart.MultipartFile;

import java.io.File;
import java.io.IOException;
import java.time.LocalDateTime;
import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;

@Slf4j
@Service
public class ImageServiceImpl implements ImageService {
    private final ObjectMapper mapper = new ObjectMapper();

    @Autowired
    private DifyProperties difyProperties;

    @Autowired
    private ImageRecordMapper imageRecordMapper;

    private Map<String, OkHttpClient> httpClients;

    @PostConstruct
    public void init() {
        // 初始化不同配置的HTTP客户端
        httpClients = new HashMap<>();
        difyProperties.getApplications().forEach((appId, app) -> {
            OkHttpClient client = new OkHttpClient.Builder()
                    .connectTimeout(difyProperties.getTimeout().getConnect(), TimeUnit.SECONDS)
                    .writeTimeout(difyProperties.getTimeout().getWrite(), TimeUnit.SECONDS)
                    .readTimeout(difyProperties.getTimeout().getRead(), TimeUnit.SECONDS)
                    .build();
            httpClients.put(appId, client);
            log.info("初始化HTTP客户端: {}, 名称: {}", appId, app.getName());
        });
    }

    @Override
    public ResponseEntity<?> uploadImage(MultipartFile file, String userId, String appId) throws IOException {
        // 获取指定的应用配置
        DifyProperties.Application app = difyProperties.getApplications().get(appId);
        if (app == null) {
            return ResponseEntity.badRequest().body("未找到指定的AI应用");
        }

        File tempFile = File.createTempFile("temp-", file.getOriginalFilename());
        try {
            file.transferTo(tempFile);

            RequestBody requestBody = new MultipartBody.Builder()
                    .setType(MultipartBody.FORM)
                    .addFormDataPart("file", tempFile.getName(),
                            RequestBody.create(MediaType.parse("image/*"), tempFile))
                    .addFormDataPart("user", userId)
                    .build();

            Request request = new Request.Builder()
                    .url(difyProperties.getUrl() + "/v1/files/upload")
                    .header("Authorization", "Bearer " + app.getKey())
                    .post(requestBody)
                    .build();

            try (Response response = httpClients.get(appId).newCall(request).execute()) {
                String responseBody = response.body() != null ? response.body().string() : null;

                if (response.isSuccessful() && responseBody != null) {
                    JsonNode jsonNode = mapper.readTree(responseBody);
                    String uploadFileId = jsonNode.path("id").asText();

                    // 保存记录
                    ImageRecord record = new ImageRecord();
                    record.setUploadFileId(uploadFileId);
                    record.setUserId(userId);
                    record.setAppId(appId); // 添加appId字段
                    record.setCreateTime(LocalDateTime.now());
                    record.setStatus(0);
                    imageRecordMapper.insert(record);

                    return ResponseEntity.ok(responseBody);
                } else {
                    return ResponseEntity.status(response.code()).body(responseBody);
                }
            }
        } finally {
            tempFile.delete();
        }
    }

    @Override
    public ChatResponse chatWithImage(String userId, String uploadFileId, String query, String appId) {
        DifyProperties.Application app = difyProperties.getApplications().get(appId);
        if (app == null) {
            return ChatResponse.builder()
                    .status("error")
                    .errorMessage("未找到指定的AI应用")
                    .build();
        }

        try {
            // 检查图片记录
            ImageRecord imageRecord = imageRecordMapper.selectOne(
                    new LambdaQueryWrapper<ImageRecord>()
                            .eq(ImageRecord::getUploadFileId, uploadFileId)
                            .eq(ImageRecord::getAppId, appId)
                            .eq(ImageRecord::getStatus, 0)
            );

            if (imageRecord == null) {
                return ChatResponse.builder()
                        .status("error")
                        .errorMessage("图片不存在或已过期")
                        .build();
            }

            // 构建聊天请求
            DifyMessageRequest messageRequest = DifyMessageRequest.builder()
                    .inputs(new HashMap<>())
                    .query(query)
                    .response_mode("blocking")
                    .user(userId)
                    .files(Collections.singletonList(
                            DifyMessageRequest.FileInfo.builder()
                                    .type("image")
                                    .transfer_method("local_file")
                                    .upload_file_id(uploadFileId)
                                    .build()
                    ))
                    .build();

            RequestBody requestBody = RequestBody.create(
                    mapper.writeValueAsString(messageRequest),
                    MediaType.parse("application/json")
            );

            Request request = new Request.Builder()
                    .url(difyProperties.getUrl() + "/v1/chat-messages")
                    .addHeader("Authorization", "Bearer " + app.getKey())
                    .post(requestBody)
                    .build();

            try (Response response = httpClients.get(appId).newCall(request).execute())  {
                if (response.isSuccessful() && response.body() != null) {
                    String responseStr = response.body().string();
                    log.info("原始响应: {}", responseStr);

                    try {
                        Map<String, Object> responseMap = mapper.readValue(responseStr,
                                new TypeReference<Map<String, Object>>() {});

                        Object answerObj = responseMap.get("answer");
                        if (answerObj == null) {
                            return ChatResponse.builder()
                                    .status("error")
                                    .errorMessage("未找到answer字段")
                                    .build();
                        }

                        String answer = answerObj.toString();
                        log.info("解析的answer: {}", answer);

                        // 解析食材信息
                        List<FoodRecognitionDTO> foods = parseFoodInfo(answer);

                        if (foods.isEmpty()) {
                            return ChatResponse.builder()
                                    .status("error")
                                    .errorMessage("未能识别任何食材信息")
                                    .build();
                        }

                        // 处理和标准化食材数据
                        foods = processFoodData(foods);

                        // 更新记录
                        imageRecord.setQuery(query);
                        imageRecord.setResponse(answer);
                        imageRecordMapper.updateById(imageRecord);

                        return ChatResponse.builder()
                                .status("success")
                                .rawAnswer(answer)
                                .foods(foods)
                                .build();

                    } catch (JsonProcessingException e) {
                        log.error("JSON处理失败", e);
                        return ChatResponse.builder()
                                .status("error")
                                .errorMessage("JSON处理失败: " + e.getMessage())
                                .build();
                    }
                } else {
                    return ChatResponse.builder()
                            .status("error")
                            .errorMessage("API调用失败: " + response.code())
                            .build();
                }
            }
        } catch (Exception e) {
            log.error("Chat with image failed", e);
            return ChatResponse.builder()
                    .status("error")
                    .errorMessage("处理失败: " + e.getMessage())
                    .build();
        }
    }



    private List<FoodRecognitionDTO> processFoodData(List<FoodRecognitionDTO> foods) {
        return foods.stream()
                .filter(this::isValidFoodData)
                .map(this::standardizeFoodData)
                .collect(Collectors.toList());
    }

    // 解析食材信息的辅助方法
    private List<FoodRecognitionDTO> parseFoodInfo(String answer) {
        List<FoodRecognitionDTO> foods = new ArrayList<>();
        try {
            // 移除句号
            answer = answer.replace("。", "");
            String[] lines = answer.split("\n");

            for (String line : lines) {
                line = line.trim();
                if (line.isEmpty()) {
                    continue;
                }

                log.info("正在解析行: {}", line);

                // 匹配两种格式：天数和周数
                Pattern pattern = Pattern.compile("(\\S+)\\s+(\\d+)(\\S+)\\s+推荐在([^\\d]+)保存(\\d+)([天周])");
                Matcher matcher = pattern.matcher(line);

                if (matcher.find()) {
                    try {
                        String name = matcher.group(1);
                        int quantity = Integer.parseInt(matcher.group(2));
                        String unit = matcher.group(3);
                        String environment = matcher.group(4);
                        int period = Integer.parseInt(matcher.group(5));
                        String periodUnit = matcher.group(6);

                        // 如果单位是周，转换为天
                        if ("周".equals(periodUnit)) {
                            period *= 7;
                        }

                        FoodRecognitionDTO food = FoodRecognitionDTO.builder()
                                .name(name)
                                .quantity(quantity)
                                .unit(unit)
                                .storage("推荐在" + environment + "保存" +
                                        (periodUnit.equals("周") ? matcher.group(5) + "周" : period + "天"))
                                .days(period)
                                .build();

                        log.info("成功解析食材: {}", food);
                        foods.add(food);

                    } catch (NumberFormatException e) {
                        log.error("解析数字失败: {}", line, e);
                    }
                } else {
                    log.warn("无法匹配行: {}", line);
                    // 尝试更宽松的匹配
                    tryAlternativeParser(line, foods);
                }
            }
        } catch (Exception e) {
            log.error("解析食材信息失败", e);
        }

        log.info("总共解析到 {} 个食材", foods.size());
        return foods;
    }

    private void tryAlternativeParser(String line, List<FoodRecognitionDTO> foods) {
        try {
            // 分步骤解析
            String[] mainParts = line.split("推荐在");
            if (mainParts.length == 2) {
                // 解析食材部分
                String[] foodParts = mainParts[0].trim().split("\\s+");
                if (foodParts.length >= 2) {
                    String name = foodParts[0];
                    String quantityWithUnit = foodParts[1];

                    // 分离数量和单位
                    Pattern numPattern = Pattern.compile("(\\d+)(\\S+)");
                    Matcher numMatcher = numPattern.matcher(quantityWithUnit);

                    if (numMatcher.find()) {
                        int quantity = Integer.parseInt(numMatcher.group(1));
                        String unit = numMatcher.group(2);

                        // 解析存储建议部分
                        String storagePart = mainParts[1].trim();
                        Pattern periodPattern = Pattern.compile("保存(\\d+)([天周])");
                        Matcher periodMatcher = periodPattern.matcher(storagePart);

                        if (periodMatcher.find()) {
                            int period = Integer.parseInt(periodMatcher.group(1));
                            String periodUnit = periodMatcher.group(2);

                            // 如果单位是周，转换为天
                            if ("周".equals(periodUnit)) {
                                period *= 7;
                            }

                            FoodRecognitionDTO food = FoodRecognitionDTO.builder()
                                    .name(name)
                                    .quantity(quantity)
                                    .unit(unit)
                                    .storage("推荐在" + mainParts[1].trim())
                                    .days(period)
                                    .build();

                            log.info("使用备选方式成功解析食材: {}", food);
                            foods.add(food);
                        }
                    }
                }
            }
        } catch (Exception e) {
            log.error("备选解析方式失败: {}", line, e);
        }
    }
    // 验证食材数据
    private boolean isValidFoodData(FoodRecognitionDTO food) {
        try {
            if (StringUtils.isEmpty(food.getName()) ||
                    food.getQuantity() == null ||
                    StringUtils.isEmpty(food.getUnit())) {
                return false;
            }

            // 检查数量是否为正数
            if (food.getQuantity() <= 0) {
                return false;
            }

            return true;
        } catch (Exception e) {
            log.error("数据验证失败", e);
            return false;
        }
    }

    // 标准化食材数据
    private FoodRecognitionDTO standardizeFoodData(FoodRecognitionDTO food) {
        return FoodRecognitionDTO.builder()
                .name(food.getName().trim())
                .quantity(food.getQuantity())
                .unit(food.getUnit().trim())
                .storage(food.getStorage())
                .days(food.getDays())
                .build();
    }


}
